package handler

import (
	"code.byted.org/mobaijie/sender/define"
	"context"
	"errors"
	"fmt"
	"io/ioutil"
	"net/smtp"
	"strings"
	"time"
)

/**
smtp客户端
*/

// auth校验类
type unencryptedAuth struct {
	smtp.Auth
}

func (a unencryptedAuth) Start(server *smtp.ServerInfo) (string, []byte, error) {
	s := *server
	s.TLS = true
	return a.Auth.Start(&s)
}

// 发送邮件（对外暴露）
func SendEmail(ctx context.Context, req *define.SmtpReq) (error, *define.SmtpResp) {
	// log.Infof("content: %s", req.HtmlBody)
	resp := &define.SmtpResp{
		SeqId:         req.SeqId,
		Headers:       make(map[string]string),
		StatusCode:    define.Success,
		StatusMessage: define.GetMessage(define.Success),
	}
	// 参数校验
	err := validateReqParam(ctx, req)
	if err != nil {
		log.Errorf("param invalid, err: %s", err.Error())
		resp.StatusCode = define.ParamErr
		resp.StatusMessage = define.GetMessage(define.ParamErr)
		return err, resp
	}
	// 发送邮件
	err = doSendEmail(ctx, req)
	if err != nil {
		log.Errorf("sendMail fail")
		resp.StatusCode = define.SendMailErr
		resp.StatusMessage = define.GetMessage(define.SendMailErr)
		return err, resp
	}
	return nil, resp
}

// 发送邮件
func doSendEmail(ctx context.Context, req *define.SmtpReq) error {
	// 飞书smtp服务器的信息
	host := define.SmtpAddress
	port := define.SmtpPort
	address := fmt.Sprintf("%s:%d", host, port)
	body := req.HtmlBody
	attachment := req.AttachmentBody
	publicMailAddress := define.PublicUserMail
	// 组装授权信息
	auth := unencryptedAuth{
		smtp.PlainAuth("", define.PublicUserMail, define.SmtpPassword, host),
	}
	rcptList := make([]string, len(req.RcptTo))
	for i := 0; i < len(req.RcptTo); i++ {
		rcptList[i] = fmt.Sprintf("<%s>", req.RcptTo[i])
		log.Infof("rcpt: %s", rcptList[i])
	}
	// 注入邮件主要内容
	content := []byte(fmt.Sprintf(define.EmlTemplate, req.MailFrom, strings.Join(rcptList, ";"), req.Subject, body, attachment))
	log.Infof("start to send email to address: %s", address)
	ioutil.WriteFile(fmt.Sprintf(define.OutputEmlFilePath, req.Tag, time.Now().UnixNano()), []byte(content), 0666)
	err := smtp.SendMail(address, auth, publicMailAddress, req.RcptTo, content)
	if err != nil {
		log.Errorf("send email to feishu smtp server fail, err: %s", err.Error())
	}
	return err
}

// 参数校验
func validateReqParam(ctx context.Context, req *define.SmtpReq) error {
	if req.SeqId == 0 {
		return errors.New("seqId invalid")
	} else if strings.TrimSpace(req.MailFrom) == "" {
		return errors.New("mailFrom invalid")
	} else if req.RcptTo == nil || len(req.RcptTo) == 0 {
		return errors.New("rcptTo invalid")
	} else if strings.TrimSpace(req.HtmlBody) == "" {
		return errors.New("htmlBody invalid")
	}
	return nil
}
